<!--todo 从SortableUpload 借鉴而来，待优化，目前去是数组模式，待优化为 -->
<template>
  <div>
    <el-radio-group v-model="radioType">
      <el-radio :label="1">外链</el-radio>
      <el-radio :label="2">上传视频</el-radio>
    </el-radio-group>

    <div v-if="radioType === 1">
      <el-input v-model="imgList[0]" clearable @change="handleChange" placeholder="请输入视频链接"></el-input>
    </div>

    <div v-else>
      <div v-if="!disabled" class="upload-copy">
        <el-input placeholder="视频复制" @paste.native="handlePost" />
      </div>
      <div class="uploadWrapper">
        <vuedraggable
          v-if="!inputDisabled"
          v-model="imgList"
          :class="{ single: isSingle, maxHidden: isMaxHidden }"
          tag="div"
          class="vue-draggable"
          draggable=".draggable-item"
          @start="onDragStart"
          @end="onDragEnd"
        >
          <!-- 拖拽元素 -->
          <div
            v-for="(item, index) in imgList"
            :key="item + index"
            class="draggable-item"
            :style="{ width: width + 'px', height: height + 'px', display: 'flex', 'align-items': 'center', 'justify-content': 'center' }"
          >
          <el-tooltip :content="item">
            <el-link type="primary">{{ `视频链接${imgList.length === 1? '' : index + 1}` }}</el-link>
          </el-tooltip>
            <div class="shadow">
              <i style="margin-left:3px" class="el-icon-close" @click="onRemoveHandler(index)" />
            </div>
            <template v-if="(!isSingle && firstAsCover && index===0) || uploadingImageIndex===index">
              <div v-if="uploadingImageIndex===index" class="cover-img-flag">
                <span>正在上传...</span>
              </div>
              <!-- <span v-else-if="!isSingle && firstAsCover && index===0" class="as-cover-img">封面</span> -->
            </template>
            <div
              v-if="uploadingImageIndex!==index"
              class="cover-img-flag cover-img-flag--preview"
              :style="{height:exchangeHeight}"
            >
              <el-upload
                class="upload"
                :action="uploadUrl"
                :http-request="customUploadRequest"
                accept=".mp4,.ogg,.flv,.avi,.wmv,.rmvb"
                :before-upload="beforeUpload4Change.bind(this,index)"
                auto-upload
                :on-success="handleChangePicSuccess.bind(this,index)"
                :headers="headers"
                :show-file-list="false"
                :limit="1"
              >
                <div>更换</div>
              </el-upload>
            </div>
          </div>
          <!-- 上传按钮 -->
          <el-upload
            v-if="!isSingle || imgList.length < 1"
            slot="footer"
            ref="uploadRef"
            class="uploadBox"
            drag
            :style="{ width: width + 'px', height: height + 'px' }"
            :action="uploadUrl"
            :http-request="customUploadRequest"
            :headers="headers"
            accept=".mp4,.ogg,.flv,.avi,.wmv,.rmvb"
            :show-file-list="false"
            :file-list="fileList"
            :multiple="!isSingle && limit>1"
            :limit="limit"
            :before-upload="beforeUpload"
            :on-success="onSuccessUpload"
            :on-exceed="onExceed"
          >
            <i class="el-icon-plus uploadIcon">
              <span v-show="isUploading" class="uploading">正在上传...</span>
              <span
                v-if="!isUploading && limit && limit!==99 && !isSingle"
                class="limitTxt"
              >最多{{ limit }}个</span>
            </i>
          </el-upload>
        </vuedraggable>
        <ul v-else class="vue-draggable">
          <li
            v-for="(item, index) in imgList"
            :key="item + index"
            class="draggable-item"
            :style="{ width: width + 'px', height: height + 'px' }"
          >
            <el-image :src="item" fit="cover" :preview-src-list="imgList" />
          </li>
        </ul>
      </div>
  </div>
  </div>
</template>

<script>
import vuedraggable from 'vuedraggable'

import lrz from 'lrz'
import Validator from '@/utils/Validator'
import { getToken } from '@/utils/auth'
import { UPLOAD_URL } from '@/infra/conf/default'
import request from '@/utils/request'
import UploaderUtil from '@/utils/upload/UploaderUtil'
import { AppVersion } from '@/framework/constant/Common'
import { defaultApi } from '@/infra/api/http/apiFactory'

export default {
  name: 'SortableUpload',

  components: { vuedraggable },

  props: {
    // 视频数据(视频url组成的数组) 通过v-model传递
    value: {
      type: [Array, String],
      default() {
        return []
      }
    },
    // 限制上传的视频数量
    limit: {
      type: Number,
      default: 9
    },
    uploadUrl: {
      type: String,
      default: UPLOAD_URL
    },
    firstAsCover: {
      type: Boolean,
      default: true
    },
    // 限制上传视频的文件大小(kb)
    size: {
      type: Number,
      default: 500*1024
    },
    // 是否是单图上传(单图上传就是已传视频和上传按钮重叠)
    isSingle: {
      type: Boolean,
      default: true
    },
    // 是否使用视频压缩
    useCompress: {
      type: Boolean,
      default: true
    },
    // 视频显示的宽度(px)
    width: {
      type: [Number, String],
      default: 100
    },
    // 视频显示的高度(px)
    height: {
      type: [Number, String],
      default: 100
    },
    disabled: {
      type: Boolean,
      default: false
    }
  },

  data() {
    return {
      radioType: 1, // 1-外链 2-上传视频
      headers: {
        Authorization: getToken(),
        token: getToken(),
        // 'X-Xsrf-Token': getXsrfToken(),
        AppVersion: AppVersion
      },
      imgList: this.getImgListFromValue(),
      fileList: [],
      uploadingImageIndex: -1,
      isUploading: false // 正在上传状态
      // isFirstMount: true // 控制防止重复回显
    }
  },

  inject: {
    elForm: {
      default: ''
    },
    elFormItem: {
      default: ''
    }
  },

  computed: {
    exchangeHeight() {
      if (this.height >= 100) {
        return '20px'
      }
      return '10px'
    },
    // 控制达到最大限制时隐藏上传按钮
    isMaxHidden() {
      return this.imgList.length >= this.limit
    },
    inputDisabled() {
      return this.disabled || (this.elForm || {}).disabled
    }
  },
  watch: {
    value() {
      this.imgList = this.getImgListFromValue()
      if (this.hasChanged) {
        this.hasChanged = false
      } else {
        this.fileList = this.getFileList()
      }
    }
  },
  mounted() {
    this.fileList = this.getFileList()
  },

  methods: {
    customUploadRequest(option) {
      const data = new FormData()
      data.append('file', option.file)
      defaultApi.post(this.uploadUrl, data).then(res => {
        option.onSuccess(res)
      }).catch(error => {
        console.log(error)
      })
    },
    handlePost(event) {
      const items = event.clipboardData && event.clipboardData.items
      // let file = null
      const fileList = []
      if (items && items.length) {
        // 检索剪切板items
        for (var i = 0; i < items.length; i++) {
          if (items[i].type.indexOf('image') !== -1) {
            // file =
            fileList.push(items[i].getAsFile())
          }
        }
      }
      if (!fileList.length) {
        return
      }
      if (this.imgList.length + fileList.length > this.limit) {
        this.$message({
          type: 'warning',
          message: `视频超限，最多可上传${this.limit}个视频`
        })
        return
      }
      fileList.forEach(file => {
        const formData = new FormData()
        formData.append('file', file)
        UploaderUtil.uploadFile({ request, uploadUrl: this.uploadUrl }, {
          file, success: (data) => {
            this.imgList.push(this.imgUrl(data))
            this.notifyChanged()
          }
        })
      })
    },
    //
    handleChange(val) {
      if (val) {
        this.imgList[0] = val
      } else {
        this.imgList = []
      }
      this.getFileList()
      this.notifyChanged()
    },
    getImgListFromValue() {
      if (this.isString()) {
        return this.value ? this.value.split(',') : []
      }
      return this.value
    },
    getFileList() {
      return this.imgList.map((el, i) => {
        return {
          url: el,
          name: 'pic' + i
        }
      })
    },
    isString() {
      return this.value === null || typeof this.value === 'string'
    },
    beforeUpload4Change(index, file) {
      if (this.useCompress) {
        // 视频压缩
        return new Promise((resolve, reject) => {
          lrz(file, { width: 1920 }).then((rst) => {
            file = rst.file
          }).always(() => {
            if (Validator.validVideoUpload(file, this.size)) {
              this.uploadingImageIndex = index
              resolve()
            } else {
              reject(new Error())
            }
          })
        })
      } else {
        if (Validator.validVideoUpload(file, this.size)) {
          this.uploadingImageIndex = index
          return true
        } else {
          return false
        }
      }
    },
    dataURItoBlob(base64Data) {
      let byteString

      if (base64Data.split(',')[0].indexOf('base64') >= 0) {
        byteString = atob(base64Data.split(',')[1])
      } else {
        byteString = unescape(base64Data.split(',')[1])
      }

      const mimeString = base64Data.split(',')[0].split(':')[1].split(';')[0]

      const ia = new Uint8Array(byteString.length)

      for (var i = 0; i < byteString.length; i++) {
        ia[i] = byteString.charCodeAt(i)
      }
      return new Blob([ia], { type: mimeString })
    },
    // 上传视频之前
    beforeUpload(file) {
      // this.isFirstMount = false
      if (this.useCompress) {
        // debugger
        // 视频压缩
        return new Promise((resolve, reject) => {
          lrz(file, { width: 1920, quality: 0.3 }).then((rst) => {
            const base64Img = rst.base64
            file = this.dataURItoBlob(base64Img)
          }).always(() => {
            if (Validator.validVideoUpload(file, this.size)) {
              this.isUploading = true
              resolve()
            } else {
              reject(new Error())
            }
          })
        })
      } else {
        if (Validator.validVideoUpload(file, this.size)) {
          this.isUploading = true
          return true
        } else {
          return false
        }
      }
    },
    notifyChanged() {
      this.hasChanged = true
      if (this.isString()) {
        this.$emit('input', this.imgList.join(','))
      } else {
        this.$emit('input', this.imgList)
      }
    },
    handleChangePicSuccess(idx, res, file, fileList) {
      // if (res.code === 200) {
      //   this.fileList[idx].url = this.imgList[idx] = this.imgUrl(res.data)
      this.fileList[idx].url = this.imgList[idx] = this.imgUrl(res)
      this.notifyChanged()
      // } else {
      //   this.$message({ type: 'error', message: res.msg })
      // }
      this.uploadingImageIndex = -1
    },
    // 上传完单个视频
    onSuccessUpload(res, file, fileList) {
      this.fileList = fileList
      // if (res.code === 200) {
      if (this.imgList.length < this.limit) {
        // this.imgList.push(this.imgUrl(res.data))
        this.imgList.push(this.imgUrl(res))
        this.notifyChanged()
      }
      // } else {
      //   this.fileList = []
      //   this.$message({ type: 'error', message: res.msg })
      // }
      this.isUploading = false
    },
    // 移除单个视频
    onRemoveHandler(index) {
      this.$confirm('确定删除该视频?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      })
        .then(() => {
          this.imgList.splice(index, 1)
          this.fileList.splice(index, 1)
          this.notifyChanged()
        })
        .catch(() => {
        })
    },
    // 超限
    onExceed() {
      this.$refs.uploadRef.abort() // 取消剩余接口请求
      // this.syncElUpload()
      this.$message({
        type: 'warning',
        message: `视频超限，最多可上传${this.limit}个视频`
      })
    },
    onDragStart(e) {
      e.target.classList.add('hideShadow')
    },
    onDragEnd(e) {
      e.target.classList.remove('hideShadow')
    }
  }
}
</script>

<style lang="scss" scoped>
::v-deep .el-upload {
  width: 100%;
  height: 100%;
}

.upload-copy {
  padding-bottom: 10px;
  width: 100px;
}

.as-cover-img {
  position: absolute;
  left: 0;
  top: 0;
  font-size: 12px;
  height: 14px;
  background: #407cff;
  border-radius: 2px 0px 3px 0px;
  font-weight: 500;
  color: #fff;
  line-height: 14px;
  text-align: center;
  padding: 0px 1px;
}

.cover-img-flag {
  position: absolute;
  bottom: 0;
  right: 0;
  line-height: 1;
  padding: 5px 0;
  text-align: center;
  color: #eee;
  font-size: 12px;
  left: 0;
  background-color: rgba(0, 0, 0, .5);

  &--preview {
    opacity: 0;
    cursor: pointer;
    height: 25px;
  }
}

.cover-img-flag--preview-img {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  bottom: 0;

  ::v-deep img {
    opacity: 0;
  }
}

.draggable-item {
  &:hover {
    .cover-img-flag--preview {
      opacity: 1;
    }
  }
}

// 上传按钮
.uploadIcon {
  width: 100%;
  height: 100%;
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px dashed #c0ccda;
  background-color: #fbfdff;
  border-radius: 6px;
  font-size: 20px;
  color: #999;

  .limitTxt,
  .uploading {
    position: absolute;
    bottom: 10%;
    left: 0;
    width: 100%;
    font-size: 14px;
    text-align: center;
  }
}

// 拖拽
.vue-draggable {
  display: flex;
  flex-wrap: wrap;

  .draggable-item {
    margin-right: 5px;
    margin-bottom: 5px;
    border: 1px solid #ddd;
    border-radius: 6px;
    position: relative;
    overflow: hidden;

    .el-image {
      width: 100%;
      height: 100%;
    }

    .shadow {
      position: absolute;
      top: 0;
      display: flex;
      align-items: center;
      right: 0;
      //opacity: 0;
      transition: opacity .3s;
      color: #fff;
      font-size: 12px;
      line-height: 14px;
      padding: 2px;
      cursor: pointer;

      background: rgba(0, 0, 0, .4);
      -moz-border-radius: 0px 2px 0px 12px;
      border-radius: 0px 2px 0px 12px;
      display: -webkit-flex;
      display: -moz-box;
      display: -ms-flexbox;
      display: flex;
      -webkit-align-content: center;
      -ms-flex-line-pack: center;
      align-content: center;
      -webkit-justify-content: center;
      -moz-box-pack: center;
      -ms-flex-pack: center;
      justify-content: center;

    }

    &:hover {
      .shadow {
        //opacity: 1;
      }
    }
  }

  &.hideShadow {
    .shadow {
      display: none;
    }
  }

  //&.single {
  //  overflow: hidden;
  //  position: relative;
  //
  //  .draggable-item {
  //    position: absolute;
  //    left: 0;
  //    top: 0;
  //    z-index: 1;
  //  }
  //}

  &.maxHidden {
    .uploadBox {
      display: none;
    }
  }
}

// el-image
.el-image-viewer__wrapper {
  .el-image-viewer__mask {
    opacity: .8;
  }

  .el-icon-circle-close {
    color: #fff;
  }
}

.upload {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  bottom: 0;

  ::v-deep .el-upload {
    display: flex;
    justify-content: center;
    align-items: center;
  }

}

.uploadBox {
  ::v-deep .el-upload-dragger {
    width: 100%;
    height: 100%;
    border: none !important;
  }

}
</style>
